import { SM } from '/@/utils/sm';
import { Session } from '/@/utils/storage';

export const Sign = {
	/**
	 * 参数签名
	 * @param options={url: string, params: object, data: object}
	 * @returns string
	 */
	signature: (options: any) => {
		const { url, params, data } = options;
		const _params = {} as any;
		const keys = Object.keys(params || {})?.sort();
		if(keys && keys.length > 0){
			for (let i = 0; i < keys.length; i++) {
				const value = params[keys[i]];
				if('Array' === Sign.dataTypeof(value)){
					if(value?.length > 0){
						_params[keys[i]] = value.toString();
					}
				} else {
					if('Undefined' !== Sign.dataTypeof(value) && 'Null' !== Sign.dataTypeof(value)) {
						_params[keys[i]] = value.toString();
					}
				}
			}
		}

		const signdata = {
			url: url || '',
			params: _params,
			data: data || {},
			secret: Math.random().toString(36).substring(2),
			timestamp: new Date().getTime() + Session.get('timediffer')
		}
		// 生成签名字符串
		const signstr = JSON.stringify(Sign.serialize(signdata));
		const signature = SM.sm3Encrypt(signstr);
		return {
			signstr: signstr,
			signature: signature,
			secret: signdata.secret,
			timestamp: signdata.timestamp,
		}
	},
	/**
	 * 参数转成字符串，并按升序排序
	 * @param obj 
	 * @returns 
	 */
	serialize: (obj: any) => {
		if(obj === null || obj === undefined) {
			return undefined;
		}
		if ('Array' === Sign.dataTypeof(obj)) {
			const arr = [...obj].sort();
			if(arr && arr.length > 0){
				const _data = [] as any;
				for (let i = 0; i < obj.length; i++) {
					arr[i] = Sign.serialize(obj[i]);
					if('Object' === Sign.dataTypeof(obj[i])){
						_data.push(JSON.stringify(arr[i]));
					}else{
						_data.push(arr[i]);
					}
				}
				return _data.sort();
			}
			return [];
		} else if ('Object' === Sign.dataTypeof(obj)) {
			const keys = Object.keys(obj)?.sort();
			if(keys && keys.length > 0){
				const _data = {} as any;
				for (let i = 0; i < keys.length; i++) {
					const _value = Sign.serialize(obj[keys[i]]);
					if(_value !== undefined){
						_data[keys[i]] = _value;
					}
				}
				return _data;
			}
			return {};
		} else if ('Number' === Sign.dataTypeof(obj) || 'Boolean' === Sign.dataTypeof(obj) || 'String' === Sign.dataTypeof(obj)) {
			return obj;
		} else if ('Undefined' === Sign.dataTypeof(obj) || 'Null' === Sign.dataTypeof(obj)) {
			return undefined;
		}
		return obj;
	},
	/**
	 * 参数类型判断
	 * @param obj 
	 * @returns 
	 */
	dataTypeof:(obj?: any) => {
		let type = Object.prototype.toString.call(obj);
		return type.substring(8, type.length - 1);
	}
}